//
//  ZSerializeZWayParseCommandsPrivate.h
//  Part of Z-Way.C library
//
//  Created by Serguei Poltorak on 08.10.2024.
//
//  Copyright (c) 2024 Z-Wave.Me
//  All rights reserved
//  info@z-wave.me
//
//  This source file is subject to the terms and conditions of the
//  Z-Wave.Me Software License Agreement which restricts the manner
//  in which it may be used.
//

#ifndef zserialize_zway_parse_commands_private_h
#define zserialize_zway_parse_commands_private_h

#include "ZSerializeCommonPrivate.h"
#include "ZSerializeDownloadPrivate.h"
#include "ZByteOperationsPrivate.h"
#include "ZStreamPrivate.h"
#include "ZWayLib.h"

#include <regex.h>

#define ZSERIALIZE_ZWAY_PARSE_NULL "null"
#define ZSERIALIZE_ZWAY_PARSE_DONGLE "zway"
#define ZSERIALIZE_ZWAY_PARSE_ZWAVE "ZWave"
#define ZSERIALIZE_ZWAY_PARSE_ZWAVE_API "ZWaveAPI"
#define ZSERIALIZE_ZWAY_PARSE_FIRMWARE_UPDATE "FirmwareUpdate"

#define ZSERIALIZE_ZWAY_PARSE_REG_EMPTY_GROUPS_0 ""
#define ZSERIALIZE_ZWAY_PARSE_REG_EMPTY_GROUPS_3 "()()()"
#define ZSERIALIZE_ZWAY_PARSE_REG_EMPTY_GROUPS_5 "()()()()()"
#define ZSERIALIZE_ZWAY_PARSE_REG_EMPTY_GROUPS_6 "()()()()()()"

#define ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_ID "\\[([0-9]+)\\]"
#define ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_ZWAVE "^/((" ZSERIALIZE_ZWAY_PARSE_ZWAVE_API ")|(" ZSERIALIZE_ZWAY_PARSE_ZWAVE "\\." ZSERIALIZE_ZWAY_PARSE_DONGLE "))/"

#define ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_CONTROLLER "controller"
#define ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DEVICES "devices"
#define ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DEVICE ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DEVICES ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_ID
#define ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_INSTANCES "instances"
#define ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_INSTANCE ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_INSTANCES ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_ID
#define ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_INSTANCE_OPTIONAL "(\\." ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_INSTANCE ")?"
#define ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_INSTANCE_MANDATORY "(" ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_INSTANCE ")"
#define ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_CCS "commandClasses"
#define ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_CC "(" ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_CCS ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_ID "|([A-Za-z0-9_]+))"
#define ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_FUNCTION "([A-Za-z0-9_]+)()()\\((.*)\\)"
#define ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DATA_SET "data.(([^ ]*)\\.value|([^ ]*)) *= *(.*)"
#define ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DATA_GET "data(([^ ]*)\\.value|([^ ]*))"

#define ZSERIALIZE_ZWAY_PARSE_DONGLE_REQUEST "/" ZSERIALIZE_ZWAY_PARSE_ZWAVE "/list"

#define ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_CONTROLLER_PATH ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_CONTROLLER "\\." ZSERIALIZE_ZWAY_PARSE_REG_EMPTY_GROUPS_6
#define ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DEVICES_PATH ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DEVICES "\\." ZSERIALIZE_ZWAY_PARSE_REG_EMPTY_GROUPS_6
#define ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DEVICE_PATH ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DEVICE "\\." ZSERIALIZE_ZWAY_PARSE_REG_EMPTY_GROUPS_5
#define ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_INSTANCE_PATH ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DEVICE "\\." ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_INSTANCE_MANDATORY "\\." ZSERIALIZE_ZWAY_PARSE_REG_EMPTY_GROUPS_3
#define ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_CC_PATH ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DEVICE ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_INSTANCE_OPTIONAL "\\." ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_CC "\\." ZSERIALIZE_ZWAY_PARSE_REG_EMPTY_GROUPS_0

#define ZSERIALIZE_ZWAY_PARSE_REG_CONTROLLER_FUNCTION "^" ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_CONTROLLER_PATH ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_FUNCTION "$"
#define ZSERIALIZE_ZWAY_PARSE_REG_CONTROLLER_DATA_SET "^" ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_CONTROLLER_PATH ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DATA_SET "$"
#define ZSERIALIZE_ZWAY_PARSE_REG_CONTROLLER_DATA_GET "^" ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_CONTROLLER_PATH ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DATA_GET "$"

#define ZSERIALIZE_ZWAY_PARSE_REG_DEVICES_FUNCTION  "^" ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DEVICES_PATH ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_FUNCTION "$"

#define ZSERIALIZE_ZWAY_PARSE_REG_DEVICE_FUNCTION "^" ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DEVICE_PATH ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_FUNCTION "$"
#define ZSERIALIZE_ZWAY_PARSE_REG_DEVICE_DATA_SET "^" ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DEVICE_PATH ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DATA_SET "$"
#define ZSERIALIZE_ZWAY_PARSE_REG_DEVICE_DATA_GET "^" ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DEVICE_PATH ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DATA_GET "$"

#define ZSERIALIZE_ZWAY_PARSE_REG_INSTANCE_FUNCTION "^" ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_INSTANCE_PATH ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_FUNCTION "$"
#define ZSERIALIZE_ZWAY_PARSE_REG_INSTANCE_DATA_SET "^" ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_INSTANCE_PATH ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DATA_SET "$"
#define ZSERIALIZE_ZWAY_PARSE_REG_INSTANCE_DATA_GET "^" ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_INSTANCE_PATH ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DATA_GET "$"

#define ZSERIALIZE_ZWAY_PARSE_REG_CC_FUNCTION "^" ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_CC_PATH ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_FUNCTION "$"
#define ZSERIALIZE_ZWAY_PARSE_REG_CC_DATA_SET "^" ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_CC_PATH ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DATA_SET "$"
#define ZSERIALIZE_ZWAY_PARSE_REG_CC_DATA_GET "^" ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_CC_PATH ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_DATA_GET "$"

#define ZSERIALIZE_ZWAY_PARSE_REG_ZWAVE_DATA ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_ZWAVE ZSERIALIZE_ZWAY_PARSE_REG_EMPTY_GROUPS_6 "Data/([0-9]+)$"
#define ZSERIALIZE_ZWAY_PARSE_REG_ZWAVE_RUN ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_ZWAVE ZSERIALIZE_ZWAY_PARSE_REG_EMPTY_GROUPS_6 "Run/(.+)$"
#define ZSERIALIZE_ZWAY_PARSE_REG_ZWAVE_INSPECT_QUEUE ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_ZWAVE ZSERIALIZE_ZWAY_PARSE_REG_EMPTY_GROUPS_6 "InspectQueue$"
#define ZSERIALIZE_ZWAY_PARSE_REG_ZWAVE_FIRMWARE_UPDATE ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_ZWAVE ZSERIALIZE_ZWAY_PARSE_REG_EMPTY_GROUPS_6 ZSERIALIZE_ZWAY_PARSE_FIRMWARE_UPDATE "/([0-9]+)$"

#define ZSERIALIZE_ZWAY_PARSE_REG_ZWAY_FUNCTION ZSERIALIZE_ZWAY_PARSE_REG_EMPTY_GROUPS_6 ZSERIALIZE_ZWAY_PARSE_REG_PREFIX_FUNCTION "$"

typedef regmatch_t _ZSerializeZWayParseCommandReg[11];

ZWEXPORT_PRIVATE ZWBOOL _zserialize_zway_parse_normalize_path(ZWSTR path);
ZWEXPORT_PRIVATE ZWError _zserialize_zway_parse_command(_ZSerializeCommonCtx_t *ctx, ZWSTR input);
ZWEXPORT_PRIVATE ZWBOOL _zserialize_zway_parse_command_match(ZWSTR input, ZWCSTR pattern, _ZSerializeZWayParseCommandReg m);
ZWEXPORT_PRIVATE ZWError _zserialize_zway_parse(const ZWay zway, const ZWSTR in, const _ZStreamHttpWrite_t *const stream, void *const ctx_stream, const ZWBOOL gzip);
ZWEXPORT_PRIVATE void _zserialize_zway_parse_init(_ZSerializeCommonCtx_t *const ctx, const ZWay zway, const _ZStreamWriter_t *const writer, void *const ctx_writer);
static inline void _zserialize_zway_parse_free(_ZSerializeCommonCtx_t *const ctx)
{
    return _zserialize_common_free(ctx);
}
ZWEXPORT_PRIVATE ZWBOOL _zserialize_zway_command_contains(ZWCSTR cmd);
ZWEXPORT_PRIVATE ZWError _zserialize_zway_common_tree_parse_to_string(const ZWay zway, time_t timestamp, const ZWBOOL is_string, _ZByteData_t *const data);
ZWEXPORT_PRIVATE ZWError _zserialize_zway_inspect_queue_parse_to_string(const ZWay zway, const ZWBOOL is_string, _ZByteData_t *const data);
ZWEXPORT_PRIVATE ZWError _zserialize_zway_parse_command_parse_to_string(const ZWay zway, ZWSTR input, const ZWBOOL is_string, _ZByteData_t *const data);

ZWEXPORT_PRIVATE ZWBOOL _zserialize_zway_is_command_upgrade(ZWCSTR cmd);
ZWEXPORT_PRIVATE ZWError _zserialize_zway_upgrade_extract_node_id(const ZWay zway, const ZWSTR command, ZWNODE *const node_id);

static inline ZWCSTR _zserialize_zway_reg_extract_path_device_id(const _ZSerializeZWayParseCommandReg m, const ZWSTR input)
{
    return &input[m[1].rm_so];
};
static inline ZWCSTR _zserialize_zway_reg_extract_path_instance_id(const _ZSerializeZWayParseCommandReg m, const ZWSTR input)
{
    const regoff_t rm_so = m[3].rm_so;
    if (rm_so == -1)
    {
        return NULL;
    }
    return &input[rm_so];
};
static inline ZWCSTR _zserialize_zway_reg_extract_path_class_id(const _ZSerializeZWayParseCommandReg m, const ZWSTR input)
{
    const regoff_t rm_so = m[5].rm_so;
    if (rm_so == -1)
    {
        return NULL;
    }
    return &input[rm_so];
};
static inline ZWCSTR _zserialize_zway_reg_extract_path_class_name(const _ZSerializeZWayParseCommandReg m, const ZWSTR input)
{
    const regoff_t rm_so = m[6].rm_so;
    if (rm_so == -1)
    {
        return NULL;
    }
    return &input[rm_so];
};
static inline ZWSTR _zserialize_zway_reg_extract_command_path(const _ZSerializeZWayParseCommandReg m, const ZWSTR input)
{
    return &input[m[7].rm_so];
};
static inline ZWSTR _zserialize_zway_reg_extract_path_arg(const _ZSerializeZWayParseCommandReg m, const ZWSTR input)
{
    const regoff_t rm_so = m[10].rm_so;
    if (rm_so == -1)
    {
        return NULL;
    }
    return &input[rm_so];
};
static inline ZWBOOL _zserialize_zway_reg_is_value(const _ZSerializeZWayParseCommandReg m)
{
    if (m[8].rm_so == -1)
    {
        return FALSE;
    }
	return TRUE;
};

static inline ZWay __zserialize_zway_parse_get_root_object(_ZSerializeCommonCtx_t *const ctx)
{
    return (ZWay)_zserialize_common_get_root_object(ctx);
};

#endif // zserialize_zway_parse_commands_private_h
